<?php
/**
 * Created by PhpStorm.
 * User: Sky
 * Date: 2017/7/27
 * Time: 上午11:31
 */

namespace app\librarys;

use Exception;
use Faker\Provider\DateTime;
use yii\helpers\Url;

class Tools
{
    /**
     * 获取当前系统时间(精确到毫秒)
     * @return float
     */
    public static function getMillisecond()
    {
        list($t1, $t2) = explode(' ', microtime());
        return (float)sprintf('%.0f', (floatval($t1) + floatval($t2)) * 1000);
    }

    /**
     * 获取当前系统时间(精确到微秒)
     * @return float
     */
    public static function getMicrosecond()
    {
        list($t1, $t2) = explode(' ', microtime());
        return (float)sprintf('%.0f', (floatval($t1) + floatval($t2)) * 1000000);
    }

    /**
     * POST请求
     * @param $url
     * @param $data
     * @param bool $JSON_UNESCAPED_UNICODE
     * @return mixed
     */
    public static function postJson($url, $data, $JSON_UNESCAPED_UNICODE = false)
    {
        if ($JSON_UNESCAPED_UNICODE) {
            $data_string = json_encode($data, JSON_UNESCAPED_UNICODE);
        } else {
            $data_string = json_encode($data);
        }
        $ch = curl_init($url);
        //https 请求
        if (strlen($url) > 5 && strtolower(substr($url, 0, 5)) == 'https') {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        }

        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
                'Content-Type: application/json',
                'Content-Length: ' . strlen($data_string),
                'charset=utf-8',)

        );

        $result = curl_exec($ch);
        return $result;
    }

    /**
     * POST提交表达请求
     * @param $url
     * @param $data
     * @return mixed
     */
    public static function postForm($url, $data)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_USERAGENT, 'Opera/9.80 (Windows NT 6.2; Win64; x64) Presto/2.12.388 Version/12.15');
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // stop verifying certificate
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
        $result = curl_exec($curl);
        curl_close($curl);

        return $result;
    }

    public static function urlBase()
    {
        if (\Yii::$app->urlManager->showScriptName == true) {
            $url = \Yii::$app->request->scriptUrl;
        } else {
            $url = Url::base();
        }
        return $url;
    }

    public static function uuid($prefix = '')
    {
        $chars = md5(uniqid(mt_rand(), true));
        $uuid = substr($chars, 0, 8) . '-';
        $uuid .= substr($chars, 8, 4) . '-';
        $uuid .= substr($chars, 12, 4) . '-';
        $uuid .= substr($chars, 16, 4) . '-';
        $uuid .= substr($chars, 20, 12);
        return $prefix . $uuid;
    }

    public static function db_uuid()
    {
        $cmd = \Yii::$app->db->createCommand("select uuid()");
        return $cmd->queryScalar();
    }

    /**
     * @param \Exception $exception
     * @return string
     */
    public static function getExceptionFullTraceAsString($exception)
    {
        $rtn = "";
        try {
            $count = 0;
            foreach ($exception->getTrace() as $frame) {
                $args = "";
                if (isset($frame['args'])) {
                    $args = array();
                    foreach ($frame['args'] as $arg) {
                        if (is_string($arg)) {
                            $args[] = "'" . $arg . "'";
                        } elseif (is_array($arg)) {
                            $args[] = "Array";
                        } elseif (is_null($arg)) {
                            $args[] = 'NULL';
                        } elseif (is_bool($arg)) {
                            $args[] = ($arg) ? "true" : "false";
                        } elseif (is_object($arg)) {
                            $args[] = get_class($arg);
                        } elseif (is_resource($arg)) {
                            $args[] = get_resource_type($arg);
                        } else {
                            $args[] = $arg;
                        }
                    }
                    $args = join(", ", $args);
                }
                $current_file = "[internal function]";
                if (isset($frame['file'])) {
                    $current_file = $frame['file'];
                }
                $current_line = "";
                if (isset($frame['line'])) {
                    $current_line = $frame['line'];
                }
                $rtn .= sprintf("#%s %s(%s): %s(%s)\n",
                    $count,
                    $current_file,
                    $current_line,
                    $frame['function'],
                    $args);
                $count++;
            }
        } catch (\Exception $ex) {
            $rtn = $exception->getTraceAsString();
        }
        return $rtn;
    }

    /**
     * 将数组按键值由低到高排序
     * @param array $array
     */
    public static function arraySort(&$array)
    {
        if (!is_array($array)) {
            return;
        }

        ksort($array);
        foreach ($array as $key => &$value) {
            if (is_object($value)) {
                $value = (array)$value;
            }
            if (is_array($value)) {
                self::arraySort($value);
            }
        }
    }

    /**
     * 验证是时间有效型
     * @param $date
     * @return bool
     */
    public static function checkDateIsValid($date)
    {
        if (strtotime($date)) {
            return true;
        }

        return false;

//        if (!preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}$/', $date)) {
//            return false;
//        }
//        return true;
    }

    /**
     * 获取随机字符串
     * @param $len
     * @param null $chars
     * @return string
     */
    public static function getRandomString($len, $chars = null)
    {
        if (is_null($chars)) {
            $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        }
        for ($i = 0, $str = '', $lc = strlen($chars) - 1; $i < $len; $i++) {
            $str .= $chars[mt_rand(0, $lc)];
        }
        return $str;
    }

    /**
     * 返回日期格式
     * @param $datetime_str
     * @param string $format
     * @return false|string
     */
    public static function dateFormat($datetime_str, $format = 'Y-m-d')
    {
        $datetime = date_create($datetime_str);
        return date_format($datetime,$format);
    }

//define(EARTH_RADIUS, 6371);//地球半径，平均半径为6371km
    /**
     *计算某个经纬度的周围某段距离的正方形的四个点
     *
     *@param lng float 经度
     *@param lat float 纬度
     *@param distance float 该点所在圆的半径，该圆与此正方形内切，默认值为0.5千米
     *@return array 正方形的四个点的经纬度坐标
     */
    public static function returnSquarePoint($lng, $lat,$distance = 0.5){
        $er = 6371;//地球半径，平均半径为6371km
        $dlng =  2 * asin(sin($distance / (2 * $er)) / cos(deg2rad($lat)));
        $dlng = rad2deg($dlng);

        $dlat = $distance/$er;
        $dlat = rad2deg($dlat);

        return array(
            'left-top'=>array('lat'=>$lat + $dlat,'lng'=>$lng-$dlng),
            'right-top'=>array('lat'=>$lat + $dlat, 'lng'=>$lng + $dlng),
            'left-bottom'=>array('lat'=>$lat - $dlat, 'lng'=>$lng - $dlng),
            'right-bottom'=>array('lat'=>$lat - $dlat, 'lng'=>$lng + $dlng)
        );
    }


    /**
     * 数字转换为对象
     * @param $array
     * @return StdClass
     */
    public static function ArrayToObject($array)
    {
        if (is_array($array)) {
            $obj = new \stdClass();
            foreach ($array as $key => $val) {
                $obj->$key = $val;
            }
        } else {
            $obj = $array;
        }
        return $obj;
    }

    /**
     * 对象转换为数组
     * @param $object
     * @return mixed
     */
    public static function ObjectToArray($object)
    {
        if (is_object($object)) {
            foreach ($object as $key => $value) {
                $array[$key] = $value;
            }
        } else {
            $array = $object;
        }
        return $array;
    }


    //region 微信支付回调签名

    /**
     * 将xml转换为数组
     * @param $xml
     * @return mixed
     * @throws Exception
     */
    public static function FromToXml($xml)
    {
        if (!$xml) {
            throw new Exception("xml数据异常！");
        }
        //将XML转为array
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $array = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $array;
    }

    /**
     * 将数组组装为url格式
     * @param $array
     * @return string
     */
    public function ToUrlParams($array)
    {
        $buff = "";
        foreach ($array as $k => $v) {
            if ($k != "sign" && $v != "" && !is_array($v)) {
                $buff .= $k . "=" . $v . "&";
            }
        }

        $buff = trim($buff, "&");
        return $buff;
    }

    /**
     * 生成签名
     * @param $array
     * @param string $mch_key 商户支付秘钥
     * @return string
     */
    public static function MakeSign($array, $mch_key)
    {
        ksort($array);
        $string = self::ToUrlParams($array);
        $string = $string . '&key=' . $mch_key;
        $string = md5($string);
        $result = strtoupper($string);
        return $result;
    }
    //endregion
}